home *** CD-ROM | disk | FTP | other *** search
Wrap
Text File | 1994-04-26 | 34.7 KB | 1,003 lines | [ TEXT/ZBAS]
'FBSpriteWorld.incl by Robert Hommel '© Copyright 1994 'All rights granted for any use whatsoever 'version 1.01b 'Disclaimer: I've tested these routines quite thoroughly on my Mac 'LC running System 7.01 and FB 1.02c. I make no promises or warranties 'of any kind. '********************************************************************* COMPILE 0, _MacsBugLabels _caseInsensitive _STRResource INCLUDE FILE _aplIncl DEFSTR LONG DEFINT A-Z '--------------------------- GLOBALS --------------------------------- GLOBALS "GraphicUtils.glbl" GLOBALS "FBSpriteWorld.glbl" END GLOBALS '------------------------- INCLUDE FILES ----------------------------- INCLUDE "TimeManager.incl" INCLUDE "GraphicUtils.incl" '--------------------------- FUNCTIONS ------------------------------- '--------------------------------------------------------------------- 'SWEnterSpriteWorld '--------------------------------------------------------------------- CLEAR LOCAL LOCAL FN SWEnterSpriteWorld 'Make sure we can run in this environment & set globals. gColorDepth=SYSTEM(_maxColors) LONG IF SYSTEM(_sysVers)>700 tmp=FN GESTALT(_gestaltTimeMgrVersion) IF tmp<_gestaltStandardTimeMgr THEN tmp=_swTimeMgrNotPresent ELSE tmp=_noErr XELSE tmp=_swNotSystemSeven END IF END FN=tmp '--------------------------------------------------------------------- 'SWGetBestPort '--------------------------------------------------------------------- CLEAR LOCAL LOCAL FN SWGetBestPort&(rectPtr&) 'Returns a pointer to a grafport based on the current screen depth. LONG IF gColorDepth = 32 '32-bit QuickDraw available? offPort& = FN GetOffScrnGWorld&(rectPtr&) 'get color gWorld the size of pict rect XELSE offPort& = FN GetOffScrnPort&(rectPtr&) 'get B&W port the size of pict rect END IF END FN=offPort& '--------------------------------------------------------------------- 'SWInitSpriteWorld '--------------------------------------------------------------------- CLEAR LOCAL LOCAL FN SWCreateSpriteWorld(spriteWorldPtr&,srcPort&,rectPtr&,pictHdl&) 'Given a valid SpriteWorld pointer, this function creates all 'associated frames and sets the boundsRect. Returns appropriate 'error code. err=0 'initialize function return var 'set boundsRect BLOCKMOVE rectPtr&,spriteWorldPtr&+_boundsRect,8 'set windowFrame spriteWorldPtr&.windowFramePtr&=srcPort& 'create backFrame offPort&=FN SWGetBestPort&(rectPtr&) LONG IF offPort& spriteWorldPtr&.backFramePtr&=offPort& 'create loadFrame offPort&=FN SWGetBestPort&(rectPtr&) LONG IF offPort& spriteWorldPtr&.loadFramePtr&=offPort& 'set backPict spriteWorldPtr&.backpictHdl&=pictHdl& XELSE err=_swOutOfMemory END IF XELSE err=_swOutOfMemory END IF END FN=err '--------------------------------------------------------------------- 'SWCreateSWFromWindow '--------------------------------------------------------------------- CLEAR LOCAL LOCAL FN SWCreateSWFromWindow(spriteWorldPtr&,srcPort&) 'Creates all associated frames and boundsRect based on a window's 'grafPort. Returns appropriate error code. savePort&=FN GetCurrPort 'save current port FN SetThePort(srcPort&) 'set port to target window LONG IF spriteWorldPtr&=_nil 'did we get it? err=_swOutOfMemory 'couldn't allocate pointer XELSE 'got it! pictHdl&=USR GETPICT(#srcPort&+_portRect) 'take snapshot of background 'initialize the new SpriteWorld based on the window err=FN SWCreateSpriteWorld(spriteWorldPtr&,srcPort&,srcPort&+_portRect,pictHdl&) END IF FN SetThePort(savePort&) 'reset port END FN=err '--------------------------------------------------------------------- 'SWDisposFrame '--------------------------------------------------------------------- CLEAR LOCAL LOCAL FN SWDisposFrame(framePtr&) 'Releases memory occupied by framePtr&. Returns osErr. osErr=FN DisposeGrafPort(framePtr&.imageMapPtr&) IF osErr=_noErr THEN osErr=FN DisposeGrafPort(framePtr&.maskMapPtr&) END FN=osErr '--------------------------------------------------------------------- 'SWDisposSprite '--------------------------------------------------------------------- CLEAR LOCAL LOCAL FN SWDisposSprite(spritePtr&,removeFrames) 'Disposes of mask region, removes time and frame tasks, and (optionally) 'removes all frames associated with spritePtr&. 'dispose mask region CALL DISPOSERGN(spritePtr&.maskRegionHdl&) 'remove time tasks FN RmvTime(spritePtr&+_frameTimeTask&) FN RmvTime(spritePtr&+_moveTimeTask&) 'if removeFrames=_zTrue, remove all frames contained in this Sprite LONG IF removeFrames FOR frame=0 TO spritePtr&.totalFrames%-1 framePtr&=[spritePtr&+_frameList+(frame*4)] osErr=FN SWDisposFrame(framePtr&) IF osErr<>_noErr THEN EXIT FN NEXT END IF END FN=osErr '--------------------------------------------------------------------- 'SWDisposSpriteWorld '--------------------------------------------------------------------- CLEAR LOCAL LOCAL FN SWDisposSpriteWorld(SWPtr&) 'Releases memory occupied by SpriteWorld Frames and disposes of any 'sprites contained by SWPtr&. 'delete backFrame and loadFrame... osErr=FN DisposeGrafPort(SWPtr&.backFramePtr&) LONG IF osErr=_noErr osErr=FN DisposeGrafPort(SWPtr&.loadFramePtr&) LONG IF osErr=_noErr 'delete all image and mask frames... FOR layer=0 TO SWPtr&.totalLayers%-1 layerPtr&=[SWPtr&+_layerList+(layer*4)] FOR sprite=0 TO {layerPtr&+_totalSprites}-1 spritePtr&=[layerPtr&+_spriteList+(sprite*4)] 'dispose sprite and remove frames if not cloned… removeFrames=NOT(spritePtr&.isClone%) osErr=FN SWDisposSprite(spritePtr&,removeFrames) IF osErr<>_noErr THEN EXIT FN NEXT NEXT KILL PICTURE SWPtr&.backPictHdl& END IF END IF END FN=osErr '--------------------------------------------------------------------- 'SWUpdateSpriteWorld '--------------------------------------------------------------------- CLEAR LOCAL LOCAL FN SWRefreshBackground(SWPtr&) 'Copies backPict to backFrame and refreshes loadframe. DIM tempRect.8 tempRect;8=SWPtr&+_boundsRect savePort&=FN GetCurrPort 'save current port FN SetThePort (SWPtr&.backFramePtr&) 'set output to backFrame CALL DRAWPICTURE(SWPtr&.backPictHdl&,tempRect) 'draw picture to backFrame 'refresh loadFrame with background FN SetThePort(SWPtr&.loadFramePtr&) 'set port to loadFrame FN CopyOffScreenBits(SWPtr&.backFramePtr&,SWPtr&.loadFramePtr&,@tempRect,@tempRect,_srcCopy,0) FN SetThePort(savePort&) 'restore port END FN '--------------------------------------------------------------------- 'SWSetBackgroundPict '--------------------------------------------------------------------- CLEAR LOCAL LOCAL FN SWSetBackgroundPict(SWPtr&,pictHdl&) 'Sets the background PICT to pictHdl&. This background will not 'appear on the screen until you call SWRefreshBackground. SWPtr&.backPictHdl&=pictHdl& END FN '--------------------------------------------------------------------- 'SWProcessSpriteWorld '--------------------------------------------------------------------- CLEAR LOCAL LOCAL FN SWProcessSpriteWorld(SWPtr&) 'Sets current rect and frame for each sprite FOR layer=0 TO SWPtr&.totalLayers%-1 layerPtr&=[SWPtr&+_layerList+(layer*4)] FOR sprite=0 TO layerPtr&.totalSprites%-1 'set current frame... spritePtr&=[layerPtr&+_spriteList+(sprite*4)] LONG IF spritePtr&.frameTTHasFired% curFrame=spritePtr&.currentFrameNum%+spritePtr&.frameAdvance% LONG IF spritePtr&.frameAdvance%>0 IF curFrame>spritePtr&.lastFrameIndex%-1 THEN curFrame=spritePtr&.firstFrameIndex% XELSE IF curFrame<spritePtr&.firstFrameIndex% THEN curFrame=spritePtr&.lastFrameIndex%-1 END IF 'is there a frame change callback? frameChangeProcPtr&=spritePtr&.frameChangeProcPtr& 'if so, call it… IF frameChangeProcPtr&<>_nil THEN CALL frameChangeProcPtr&(spritePtr&,curFrame) spritePtr&.currentFrameNum%=curFrame 'update frame time task LONG IF spritePtr&.frameTimeInterval%>0 spritePtr&.frameTTHasFired%=_false FN PrimeTime(spritePtr&+_frameTimeTask&,spritePtr&.frameTimeInterval%) END IF 'set draw & erase flags LONG IF spritePtr&.isVisible% spritePtr&.needsToBeDrawn%=_zTrue spritePtr&.needsToBeErased%=_zTrue END IF END IF 'move sprite.... LONG IF spritePtr&.moveTTHasFired% 'call moveProc moveProcPtr&=spritePtr&.moveProcPtr& CALL moveProcPtr&(SWPtr&,spritePtr&,spritePtr&+_currentRect) 'move currentRect(faster than OffsetRect!) spritePtr&.currentRect.top%=spritePtr&.currentRect.top%+spritePtr&.yDelta% spritePtr&.currentRect.left%=spritePtr&.currentRect.left%+spritePtr&.xDelta% spritePtr&.currentRect.bottom%=spritePtr&.currentRect.bottom%+spritePtr&.yDelta% spritePtr&.currentRect.right%=spritePtr&.currentRect.right%+spritePtr&.xDelta% 'update move time task LONG IF spritePtr&.moveTimeInterval%>0 spritePtr&.moveTTHasFired%=_false FN PrimeTime(spritePtr&+_moveTimeTask&,spritePtr&.moveTimeInterval%) END IF 'set draw & erase flags LONG IF spritePtr&.isVisible% spritePtr&.needsToBeDrawn%=_zTrue spritePtr&.needsToBeErased%=_zTrue END IF END IF NEXT NEXT END FN '--------------------------------------------------------------------- 'SWAnimateSpriteWorld '--------------------------------------------------------------------- CLEAR LOCAL LOCAL FN SWAnimateSpriteWorld(SWPtr&) 'Draws sprites onto loadFrame and copies appropriate portions of 'loadFrame to screen. DIM tempRect.8 savePort&=FN GetCurrPort FN SetThePort(SWPtr&.loadFramePtr&) 'erase sprites FOR layer=0 TO SWPtr&.totalLayers%-1 layerPtr&=[SWPtr&+_layerList+(layer*4)] FOR sprite=0 TO layerPtr&.totalSprites%-1 spritePtr&=[layerPtr&+_spriteList+(sprite*4)] LONG IF spritePtr&.needsToBeErased% 'erase sprite by copying piece of backFrame to loadFrame FN CopyOffScreenBits(SWPtr&.backFramePtr&,SWPtr&.loadFramePtr&,spritePtr&+_oldRect,spritePtr&+_oldRect,_srcCopy,_nil) 'check to see if we erased any non-moving sprites… FOR tgtLayer=0 TO SWPtr&.totalLayers%-1 tgtLayerPtr&=[SWPtr&+_layerList+(tgtLayer*4)] FOR tgtSprite=0 TO tgtLayerPtr&.totalSprites%-1 tgtSpritePtr&=[tgtLayerPtr&+_spriteList+(tgtSprite*4)] LONG IF tgtSpritePtr&.needsToBeDrawn%=_false AND tgtSpritePtr&.isVisible% LONG IF FN SECTRECT(#spritePtr&+_oldRect,#tgtSpritePtr&+_currentRect,tempRect) '…if so, make sure we redraw them tgtSpritePtr&.drawPartial%=_zTrue 'get union of deltaRect and tempRect (faster than UnionRect!) IF tgtSpritePtr&.deltaRect.top%>tempRect.top% THEN tgtSpritePtr&.deltaRect.top%=tempRect.top% IF tgtSpritePtr&.deltaRect.left%>tempRect.left% THEN tgtSpritePtr&.deltaRect.left%=tempRect.left% IF tgtSpritePtr&.deltaRect.bottom%<tempRect.bottom% THEN tgtSpritePtr&.deltaRect.bottom%=tempRect.bottom% IF tgtSpritePtr&.deltaRect.right%<tempRect.right% THEN tgtSpritePtr&.deltaRect.right%=tempRect.right% END IF END IF NEXT NEXT END IF NEXT NEXT 'draw sprites in their new positions FOR layer=0 TO SWPtr&.totalLayers%-1 layerPtr&=[SWPtr&+_layerList+(layer*4)] FOR sprite=0 TO layerPtr&.totalSprites%-1 spritePtr&=[layerPtr&+_spriteList+(sprite*4)] LONG IF spritePtr&.needsToBeDrawn% OR spritePtr&.drawPartial% LONG IF spritePtr&.drawPartial% CALL RECTRGN(spritePtr&.maskRegionHdl&,spritePtr&.deltaRect&) maskRgnHdl&=spritePtr&.maskRegionHdl& spritePtr&.drawPartial%=_false 'clear deltaRect CALL SETRECT(spritePtr&.deltaRect&,0,0,0,0) XELSE maskRgnHdl&=_nil END IF framePtr&=[spritePtr&+_frameList+({spritePtr&+_currentFrameNum}*4)] 'draw mask frame FN CopyOffScreenBits(framePtr&.maskMapPtr&,SWPtr&.loadFramePtr&,framePtr&+_fBoundsRect,spritePtr&+_currentRect,_srcBic,maskRgnHdl&) 'draw image frame FN CopyOffScreenBits(framePtr&.imageMapPtr&,SWPtr&.loadFramePtr&,framePtr&+_fBoundsRect,spritePtr&+_currentRect,_srcOr,maskRgnHdl&) END IF NEXT NEXT FN SetThePort(SWPtr&.windowFramePtr&) 'copy loadFrame to screen FOR layer=0 TO SWPtr&.totalLayers%-1 layerPtr&=[SWPtr&+_layerList+(layer*4)] FOR sprite=0 TO layerPtr&.totalSprites%-1 spritePtr&=[layerPtr&+_spriteList+(sprite*4)] LONG IF spritePtr&.needsToBeDrawn% OR spritePtr&.needsToBeErased% 'get union of oldRect and newRect (faster than UnionRect!) IF spritePtr&.currentRect.top%>spritePtr&.oldRect.top% THEN spritePtr&.deltaRect.top%=spritePtr&.oldRect.top% ELSE spritePtr&.deltaRect.top%=spritePtr&.currentRect.top% IF spritePtr&.currentRect.left%>spritePtr&.oldRect.left% THEN spritePtr&.deltaRect.left%=spritePtr&.oldRect.left% ELSE spritePtr&.deltaRect.left%=spritePtr&.currentRect.left% IF spritePtr&.currentRect.bottom%<spritePtr&.oldRect.bottom% THEN spritePtr&.deltaRect.bottom%=spritePtr&.oldRect.bottom% ELSE spritePtr&.deltaRect.bottom%=spritePtr&.currentRect.bottom% IF spritePtr&.currentRect.right%<spritePtr&.oldRect.right% THEN spritePtr&.deltaRect.right%=spritePtr&.oldRect.right% ELSE spritePtr&.deltaRect.right%=spritePtr&.currentRect.right% 'set mask region equal to deltaRect CALL RECTRGN(spritePtr&.maskRegionHdl&,#spritePtr&+_deltaRect) FN CopyOffScreenBits(SWPtr&.loadFramePtr&,SWPtr&.windowFramePtr&,spritePtr&+_deltaRect,spritePtr&+_deltaRect,_srcCopy,spritePtr&.maskRegionHdl&) 'clear draw & erase flags spritePtr&.needsToBeDrawn%=_false spritePtr&.needsToBeErased%=_false END IF 'set old rect BLOCKMOVE spritePtr&+_currentRect,spritePtr&+_oldRect,8 NEXT NEXT FN SetThePort(savePort&) END FN '--------------------------------------------------------------------- 'SWAddLayerToWorld '--------------------------------------------------------------------- CLEAR LOCAL LOCAL FN SWAddLayerToWorld(SWPtr&,layerPtr&) 'Adds layerPtr& to specified SpriteWorld. LONG IF SWPtr&.totalLayers%<_maxLayers offset=SWPtr&.totalLayers%*4 POKE LONG SWPtr&+_layerList+offset,layerPtr& INC(SWPtr&.totalLayers%) XELSE err=_swTooManyLayers END IF END FN=err '--------------------------------------------------------------------- 'SWFrameFromPict '--------------------------------------------------------------------- CLEAR LOCAL LOCAL FN SWFrameFromPict(framePtr&,pictID) 'Creates image and mask frames from specified PICT resource. DIM frameRect.8 maskID=pictID+2 savePort&=FN GetCurrPort LONG IF gColorDepth<>32 'no 32-bit QuickDraw? INC(pictID) '...then get B/W pict END IF 'create imageFrame... pict&=FN GETPICTURE(pictID) err=FN RESERROR LONG IF err=_noErr frameRect;8=[pict&]+_picFrame 'make sure we're at 0,0 CALL OFFSETRECT(frameRect,-frameRect.left%,-frameRect.top%) 'copy frameRect to FramePtr.fBoundsRect BLOCKMOVE @frameRect,framePtr&+_fBoundsRect,8 'create off screen port for image offPort&=FN SWGetBestPort&(@frameRect) LONG IF offPort& framePtr&.imageMapPtr&=offPort& FN SetThePort(offPort&) CALL DRAWPICTURE(pict&,frameRect) 'draw picture to imageFrame KILL PICTURE pict& XELSE err=_swOutOfMemory END IF 'create maskFrame... pict&=FN GETPICTURE(maskID) err=FN RESERROR LONG IF err=_noErr 'create off screen port for mask offPort&=FN SWGetBestPort&(@frameRect) LONG IF offPort& framePtr&.maskMapPtr&=offPort& FN SetThePort(offPort&) CALL DRAWPICTURE(pict&,frameRect) 'draw picture to imageFrame KILL PICTURE pict& XELSE err=_swOutOfMemory END IF END IF END IF FN SetThePort(savePort&) END FN=err '--------------------------------------------------------------------- 'SWAddFrameToSprite '--------------------------------------------------------------------- CLEAR LOCAL LOCAL FN SWAddFrameToSprite(spritePtr&,framePtr&) 'Adds framePtr& to specified sprite. LONG IF spritePtr&.totalFrames%<_maxFrames offset=spritePtr&.totalFrames%*4 POKE LONG spritePtr&+_frameList+offset,framePtr& INC(spritePtr&.totalframes%) spritePtr&.lastFrameIndex%=spritePtr&.totalFrames% XELSE err=_swTooManyFrames END IF END FN=err '--------------------------------------------------------------------- 'SWInitSprite '--------------------------------------------------------------------- CLEAR LOCAL LOCAL FN SWInitSprite(spritePtr&,curFrame,curRectP&,boundsRectP&,vis,xDelta,yDelta,frameAdvance,ttPtr&,movePtr&) 'Given a pointer to a previously dimmed Sprite, sets initial values 'of a Sprite. spritePtr&.currentFrameNum%=curFrame BLOCKMOVE curRectP&,spritePtr&+_currentRect,8 BLOCKMOVE curRectP&,spritePtr&+_oldRect,8 BLOCKMOVE boundsRectP&,spritePtr&+_sBoundsRect,8 spritePtr&.isVisible%=vis spritePtr&.needsToBeErased%=_false spritePtr&.needsToBeDrawn%=_zTrue spritePtr&.drawPartial%=_false spritePtr&.totalFrames%=0 spritePtr&.firstFrameIndex%=0 spritePtr&.lastFrameIndex%=0 spritePtr&.xDelta%=xDelta spritePtr&.yDelta%=yDelta spritePtr&.maskRegionHdl&=FN NEWRGN spritePtr&.frameAdvance%=frameAdvance spritePtr&.frameTimeTask.qLink&=_nil spritePtr&.frameTimeTask.qType%=0 spritePtr&.frameTimeTask.tmAddr&=ttPtr& spritePtr&.frameTimeTask.tmCount&=0 spritePtr&.frameTimeTask.tmWakeUp&=0 spritePtr&.frameTimeTask.tmReserved&=0 spritePtr&.frameTTHasFired%=_zTrue spritePtr&.frameTimeInterval%=0 spritePtr&.frameChangeProcPtr&=_nil spritePtr&.moveTimeTask.qLink&=_nil spritePtr&.moveTimeTask.qType%=0 spritePtr&.moveTimeTask.tmAddr&=ttPtr& spritePtr&.moveTimeTask.tmCount&=0 spritePtr&.moveTimeTask.tmWakeUp&=0 spritePtr&.moveTimeTask.tmReserved&=0 spritePtr&.moveTTHasFired%=_zTrue spritePtr&.moveTimeInterval%=0 spritePtr&.moveProcPtr&=movePtr& spritePtr&.collideProcPtr&=_nil spritePtr&.isClone%=_false 'install time tasks FN InsXTime(spritePtr&.frameTimeTask&) FN InsXTime(spritePtr&.moveTimeTask&) END FN '--------------------------------------------------------------------- 'SWCloneSprite '--------------------------------------------------------------------- CLEAR LOCAL LOCAL FN SWCloneSprite(srcSpritePtr&,cloneSpritePtr&,ttPtr&) 'A cloned sprite is an exact duplicate of its source. If you have 'assigned frames to the source sprite, the framelist of the clone 'will contain pointers to those same frames. Thus, cloned sprites 'can share the same frames with their sources, which saves memory 'and processing time. The isClone field is set TRUE for cloned 'sprites, so we can determine whether to remove frames from memory 'when disposing of a sprite (generally, you will only remove frames 'when disposing of a non-cloned sprite). 'copy srcSprite data to cloneSprite BLOCKMOVE srcSpritePtr&,cloneSpritePtr&,_SWSpriteRec 'frame time tasks are unique to each sprite… cloneSpritePtr&.frameTimeTask.qLink&=_nil cloneSpritePtr&.frameTimeTask.qType%=0 cloneSpritePtr&.frameTimeTask.tmAddr&=ttPtr& cloneSpritePtr&.frameTimeTask.tmCount&=0 cloneSpritePtr&.frameTimeTask.tmWakeUp&=0 cloneSpritePtr&.frameTimeTask.tmReserved&=0 cloneSpritePtr&.frameTTHasFired%=_zTrue cloneSpritePtr&.frameTimeInterval%=0 'so are mask regions… spritePtr&.maskRegionHdl&=FN NEWRGN 'and so are move time tasks… cloneSpritePtr&.moveTimeTask.qLink&=_nil cloneSpritePtr&.moveTimeTask.qType%=0 cloneSpritePtr&.moveTimeTask.tmAddr&=ttPtr& cloneSpritePtr&.moveTimeTask.tmCount&=0 cloneSpritePtr&.moveTimeTask.tmWakeUp&=0 cloneSpritePtr&.moveTimeTask.tmReserved&=0 cloneSpritePtr&.moveTTHasFired%=_zTrue cloneSpritePtr&.moveTimeInterval%=0 'mark sprite as cloned cloneSpritePtr&.isClone%=_zTrue 'install time tasks FN InsXTime(cloneSpritePtr&.frameTimeTask&) FN InsXTime(cloneSpritePtr&.moveTimeTask&) END FN '--------------------------------------------------------------------- 'SWSpriteFromPict '--------------------------------------------------------------------- CLEAR LOCAL DIM frameRect.8 LOCAL FN SWSpriteFromPict(spritePtr&,curFrame,curX,curY,boundsRectP&,vis,xDelta,yDelta,frameAdvance,ttPtr&,movePtr&,pictID) 'Inits a Sprite based on pictID (that is, its curRect field is based 'on the size of pictID, offset to curX,curY. Returns resErr. pict&=FN GETPICTURE(pictID) resErr=FN RESERROR LONG IF resErr=_noErr frameRect;8=[pict&]+_picFrame 'pin rect to curX,curY… CALL OFFSETRECT(frameRect,curX-frameRect.left%,curY-frameRect.top%) FN SWInitSprite(spritePtr&,curFrame,@frameRect,boundsRectP&,vis,xDelta,yDelta,frameAdvance,ttPtr&,movePtr&) END IF END FN=resErr '--------------------------------------------------------------------- 'SWAddSpriteToLayer '--------------------------------------------------------------------- CLEAR LOCAL LOCAL FN SWAddSpriteToLayer(layerPtr&,spritePtr&) 'Adds spritePtr& to the specified layer. LONG IF layerPtr&.totalSprites%<_maxSprites offset=layerPtr&.totalSprites%*4 POKE LONG layerPtr&+_spriteList+offset,spritePtr& INC(layerPtr&.totalSprites%) XELSE err=_swTooManySprites END IF END FN=err '--------------------------------------------------------------------- 'SWSetSpriteMoveProc '--------------------------------------------------------------------- CLEAR LOCAL LOCAL FN SWSetSpriteMoveProc(spritePtr&,moveProcPtr&) 'Sets the movement procedure for a sprite. spritePtr&.moveProcPtr&=moveProcPtr& END FN '--------------------------------------------------------------------- 'SWSetCollideProc '--------------------------------------------------------------------- CLEAR LOCAL LOCAL FN SWSetCollideProc(spritePtr&,collideProcPtr&) 'Set the collide procedure for a sprite. spritePtr&.collideProcPtr&=collideProcPtr& END FN '--------------------------------------------------------------------- 'SWSetFrameChangeProc '--------------------------------------------------------------------- CLEAR LOCAL LOCAL FN SWSetFrameChangeProc(spritePtr&,frameChangeProcPtr&) 'Sets the frame change procedure for a sprite. spritePtr&.frameChangeProcPtr&=frameChangeProcPtr& END FN '--------------------------------------------------------------------- 'SWSetMoveDelta '--------------------------------------------------------------------- CLEAR LOCAL LOCAL FN SWSetMoveDelta(spritePtr&,xDelta,yDelta) 'Sets the number of pixels a sprite should be moved by SWProcessSpriteWorld 'horizontally and vertically. spritePtr&.xDelta%=xDelta spritePtr&.yDelta%=yDelta END FN '--------------------------------------------------------------------- 'SWOffsetSprite '--------------------------------------------------------------------- CLEAR LOCAL LOCAL FN SWOffsetSprite(spritePtr&,xDelta,yDelta) 'Moves sprite to a relative position on the screen. spritePtr&.currentRect.top%=spritePtr&.currentRect.top%+yDelta spritePtr&.currentRect.left%=spritePtr&.currentRect.left%+xDelta spritePtr&.currentRect.bottom%=spritePtr&.currentRect.bottom%+yDelta spritePtr&.currentRect.right%=spritePtr&.currentRect.right%+yDelta LONG IF spritePtr&.isVisible% spritePtr&.needsToBeErased%=_zTrue spritePtr&.needsToBeDrawn%=_zTrue END IF END FN '--------------------------------------------------------------------- 'SWSetSpriteFrameAdv '--------------------------------------------------------------------- CLEAR LOCAL LOCAL FN SWSetSpriteFrameAdv(spritePtr&,frameAdv) 'Sets the number by which SWProcessSpriteWorld will advance the current 'frame. spritePtr&.frameAdvance%=frameAdv END FN '--------------------------------------------------------------------- 'SWSetCurrentFrame '--------------------------------------------------------------------- CLEAR LOCAL LOCAL FN SWSetCurrentFrame(spritePtr&,frameNum) 'Sets the sprite's current frame. spritePtr&.currentFrameNum%=frameNum END FN '--------------------------------------------------------------------- 'SWSetSpriteVisible '--------------------------------------------------------------------- CLEAR LOCAL LOCAL FN SWSetSpriteVisible(spritePtr&,vis) 'Causes a sprite to appear or disappear. spritePtr&.isVisible%=vis spritePtr&.needsToBeDrawn%=vis spritePtr&.needsToBeErased%=NOT(vis) END FN '--------------------------------------------------------------------- 'SWGetCurRect '--------------------------------------------------------------------- CLEAR LOCAL DIM rect.8 LOCAL FN SWGetCurRect(spritePtr&,rect;8) 'Returns sprite's currentRect. BLOCKMOVE spritePtr&+_currentRect,@rect,8 END FN '--------------------------------------------------------------------- 'SWSetCurRect '--------------------------------------------------------------------- CLEAR LOCAL DIM rect.8 LOCAL FN SWSetCurRect(spritePtr&,rect;8) 'Sets current and old rect of sprite. BLOCKMOVE @rect,spritePtr&+_currentRect,8 BLOCKMOVE @rect,spritePtr&+_oldRect,8 END FN '--------------------------------------------------------------------- 'SWSetSpriteLocation '--------------------------------------------------------------------- CLEAR LOCAL LOCAL FN SWSetSpriteLocation(spritePtr&,x,y) 'Sets current and old location of sprite, based on x,y coordinates. CALL OFFSETRECT(#spritePtr&+_currentRect,x-spritePtr&.currentRect.left%,y-spritePtr&.currentRect.top%) BLOCKMOVE spritePtr&+_currentRect,spritePtr&+_oldRect,8 END FN '--------------------------------------------------------------------- 'SWMoveSpriteRect '--------------------------------------------------------------------- CLEAR LOCAL DIM rect.8 LOCAL FN SWMoveSpriteRect(spritePtr&,rect;8) 'Moves sprite to new rectangle. BLOCKMOVE @rect,spritePtr&+_currentRect,8 LONG IF spritePtr&.isVisible% spritePtr&.needsToBeErased%=_zTrue spritePtr&.needsToBeDrawn%=_zTrue END IF END FN '--------------------------------------------------------------------- 'SWMoveSprite '--------------------------------------------------------------------- CLEAR LOCAL LOCAL FN SWMoveSprite(spritePtr&,x,y) 'Moves sprite to new x,y coordinates. CALL OFFSETRECT(#spritePtr&+_currentRect,x-spritePtr&.currentRect.left%,y-spritePtr&.currentRect.top%) LONG IF spritePtr&.isVisible% spritePtr&.needsToBeErased%=_zTrue spritePtr&.needsToBeDrawn%=_zTrue END IF END FN '--------------------------------------------------------------------- 'SWSetMoveBounds '--------------------------------------------------------------------- CLEAR LOCAL DIM rect.8 LOCAL FN SWSetMoveBounds(spritePtr&,rect;8) 'Sets the bounding rectangle of the specified sprite. BLOCKMOVE @rect,spritePtr&+_sBoundsRect,8 END FN '--------------------------------------------------------------------- 'SWSetFrameRange '--------------------------------------------------------------------- CLEAR LOCAL LOCAL FN SWSetFrameRange(spritePtr&,firstFrame,lastFrame) 'Sets the range of frame indexes to be interated in SWProcessSpriteWorld. spritePtr&.firstFrameIndex%=firstFrame spritePtr&.lastFrameIndex%=lastFrame END FN '--------------------------------------------------------------------- 'SWIsSpriteInRect '--------------------------------------------------------------------- CLEAR LOCAL DIM rect.8 LOCAL FN SWIsSpriteInRect(spritePtr&,rect;8) 'Returns _zTrue (-1) if sprite's current rect is equal to or 'contained in rect. END FN=(spritePtr&.currentRect.top%>=rect.top% AND spritePtr&.currentRect.left%>=rect.left% AND spritePtr&.currentRect.bottom%<=rect.bottom% AND spritePtr&.currentRect.right%<=rect.right%) '--------------------------------------------------------------------- 'SWSpriteSectRect '--------------------------------------------------------------------- CLEAR LOCAL DIM rect.8 LOCAL FN SWSpriteSectRect(spritePtr&,rect;8,sectRectPtr&) 'Returns _zTrue (-1) if the sprite's current rect intersects 'rect. If there is an intersection, sectRect will contain the 'intersecting rectangle. END FN=-(FN SECTRECT(#spritePtr&+_currentRect,rect,#sectRectPtr&)) '--------------------------------------------------------------------- 'SWRemoveLayer '--------------------------------------------------------------------- CLEAR LOCAL LOCAL FN SWRemoveLayer(SWPtr&,layerPtr&) 'Removes a layer from the specified SpriteWorld. 'find layer in layerlist FOR x=0 TO SWPtr&.totalLayers%-1 targetLayer&=[SWPtr&+_layerList+(x*4)] LONG IF layerPtr&=targetLayer& 'delete layer and adjust layerList FOR layer=x TO SWPtr&.totalLayers%-2 &SWPtr&+_layerList+(layer*4),[SWPtr&+_layerList+((layer+1)*4)] NEXT &SWPtr&+_layerList+((SWPtr&.totalLayers%-1)*4),_nil DEC(SWPtr&.totalLayers%) EXIT FOR END IF NEXT END FN '--------------------------------------------------------------------- 'SWRemoveSprite '--------------------------------------------------------------------- CLEAR LOCAL LOCAL FN SWRemoveSprite(layerPtr&,spritePtr&) 'Removes a sprite from the specified layer. Does not dispose of the 'sprite. 'find sprite in spritelist FOR x=0 TO layerPtr&.totalSprites%-1 targetSprite&=[layerPtr&+_spriteList+(x*4)] LONG IF spritePtr&=targetSprite& 'delete sprite and adjust spriteList FOR sprite=x TO layerPtr&.totalSprites%-2 &layerPtr&+_spriteList+(sprite*4),[layerPtr&+_spriteList+((sprite+1)*4)] NEXT &layerPtr&+_spriteList+((layerPtr&.totalSprites%-1)*4),_nil DEC(layerPtr&.totalSprites%) EXIT FOR END IF NEXT END FN '--------------------------------------------------------------------- 'SWRemoveFrame '--------------------------------------------------------------------- CLEAR LOCAL LOCAL FN SWRemoveFrame(spritePtr&,framePtr&) 'Removes a frame from the specified sprite. Does not dispose of the 'frame. 'find frame in framelist FOR x=0 TO spritePtr&.totalFrames%-1 targetFrame&=[spritePtr&+_frameList+(x*4)] LONG IF framePtr&=targetFrame& 'delete frame and adjust frameList FOR frame=x TO spritePtr&.totalFrames%-2 &spritePtr&+_frameList+(frame*4),[spritePtr&+_frameList+((frame+1)*4)] NEXT &spritePtr&+_frameList+((spritePtr&.totalFrames%-1)*4),_nil DEC(spritePtr&.totalFrames%) 'adjust lastFrameIndex, if necessary IF spritePtr&.totalFrames%<spritePtr&.lastFrameIndex% THEN spritePtr&.lastFrameIndex%=spritePtr&.totalFrames% EXIT FOR END IF NEXT END FN '--------------------------------------------------------------------- 'SWIsTaskPrimed '--------------------------------------------------------------------- CLEAR LOCAL LOCAL FN SWIsTaskPrimed(tmTaskPtr&) 'Returns _zTrue if timeTask has been primed . END FN=((tmTaskPtr&.qType% AND &8000)<>0) '--------------------------------------------------------------------- 'SWSetFrameTime '--------------------------------------------------------------------- CLEAR LOCAL LOCAL FN SWSetFrameTime(spritePtr&,timeInterval) 'Sets the time in milliseconds between frame changes. spritePtr&.frameTimeInterval%=timeInterval LONG IF timeInterval>0 'if task not primed… LONG IF (NOT FN SWIsTaskPrimed(spritePtr&.frameTimeTask&)) '…prime it spritePtr&.frameTTHasFired%=_zTrue END IF XELSE 'is the time interval negative? LONG IF timeInterval<0 'if the task is primed… LONG IF FN SWIsTaskPrimed(spritePtr&.frameTimeTask&) '…remove it FN RmvTime(spritePtr&.frameTimeTask&) FN InsXTime(spritePtr&.frameTimeTask&) END IF 'the timeInterval is negative, which means never change the frame spritePtr&.frameTTHasFired%=_false XELSE 'time interval=0; this means change frames as quickly as possible spritePtr&.frameTTHasFired%=_zTrue END IF END IF END FN '--------------------------------------------------------------------- 'SWSetMoveTime '--------------------------------------------------------------------- CLEAR LOCAL LOCAL FN SWSetMoveTime(spritePtr&,timeInterval) 'Sets the time in milliseconds between sprite moves. spritePtr&.moveTimeInterval%=timeInterval LONG IF timeInterval>0 'if task not primed… LONG IF (NOT FN SWIsTaskPrimed(spritePtr&.moveTimeTask&)) '…prime it spritePtr&.moveTTHasFired%=_zTrue END IF XELSE 'is the time interval negative? LONG IF timeInterval<0 'if the task is primed… LONG IF FN SWIsTaskPrimed(spritePtr&.moveTimeTask&) '…remove it FN RmvTime(spritePtr&.moveTimeTask&) FN InsXTime(spritePtr&.moveTimeTask&) END IF 'the timeInterval is negative, which means never move sprite spritePtr&.moveTTHasFired%=_false XELSE 'time interval=0; this means move sprite as quickly as possible spritePtr&.moveTTHasFired%=_zTrue END IF END IF END FN '--------------------------------------------------------------------- 'SWUpdateSpriteWorld '--------------------------------------------------------------------- CLEAR LOCAL LOCAL FN SWUpdateSpriteWorld(SWPtr&) 'Copies entire loadframe to screen. Used to refesh screen following 'an update event. FN CopyOffScreenBits(SWPtr&.loadFramePtr&,SWPtr&.windowFramePtr&,SWPtr&+_boundsRect,SWPtr&+_boundsRect,_srcCopy,_nil) END FN '--------------------------------------------------------------------- 'SWCollideSpriteLayer '--------------------------------------------------------------------- CLEAR LOCAL DIM srcRect.8,destRect.8,sectRect.8 LOCAL FN SWCollideSpriteLayer(srcLayerPtr&,destLayerPtr&) 'Detects collisions between sprites in srcLayer and sprites in 'destLayer. If collision is detected, calls collideProc of srcSprite. 'To detect collisions between sprites in the same layer, pass the 'same layer variable in both srcLayerPtr& and destLayerPtr&. FOR srcSprite=0 TO srcLayerPtr&.totalSprites%-1 srcSpritePtr&=[srcLayerPtr&+_spriteList+(srcSprite*4)] FOR destSprite=0 TO destLayerPtr&.totalSprites%-1 destSpritePtr&=[destLayerPtr&+_spriteList+(destSprite*4)] LONG IF srcSpritePtr&<>destSpritePtr& LONG IF FN SECTRECT(#srcSpritePtr&+_currentRect,#destSpritePtr&+_currentRect,sectRect) collideProcPtr&=srcSpritePtr&.collideProcPtr& IF collideProcPtr&<>_nil THEN CALL collideProcPtr&(srcSpritePtr&,destSpritePtr&,@sectRect) END IF END IF NEXT NEXT END FN